using System;
using Thrift;          
using Thrift.Transport; 
using Thrift.Transport.Client;  
using Thrift.Protocol;
using static CtrlThrApi; 


namespace CtrlThrApi_CSharp
{
    public class CtrlThrApiClientWrapper : IDisposable
    {
        private TTransport _transport;
        private CtrlThrApi.Client _client;
        private bool _isConnected = false;
        private string _serverIp;
        private int _serverPort;
        private string _authToken; // 新增成员变量保存Token

        public CtrlThrApi.Client Client 
        { 
            get 
            {
                if (!_isConnected)
                    throw new InvalidOperationException("Client is not connected. Call ConnectAsync first.");
                return _client; 
            } 
        }

        public async System.Threading.Tasks.Task ConnectAsync(string ip , int port )
        {
            // Store server info for potential reconnections
            _serverIp = ip;
            _serverPort = port;
            
            if (!_isConnected)
            {
                await CreateNewConnection(ip, port);
            }
        }
        
        private async System.Threading.Tasks.Task CreateNewConnection(string ip, int port)
        {
            _transport = new TSocketTransport(System.Net.IPAddress.Parse(ip), port, new TConfiguration());
            TProtocol protocol = new TBinaryProtocol(_transport);
            _client = new CtrlThrApi.Client(protocol);

            await _transport.OpenAsync();
            _isConnected = true;
        }

        public async System.Threading.Tasks.Task<bool> TryReconnectAsync()
        {
            try
            {
                Disconnect();
                if (!string.IsNullOrEmpty(_serverIp))
                {
                    await ConnectAsync(_serverIp, _serverPort);
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        public async System.Threading.Tasks.Task<bool> IsServerAvailableAsync()
        {
            try
            {
                if (_isConnected && _transport != null)
                {
                    // Try a simple operation to check if connection is still alive
                    // Using a real ping-like operation instead of just FlushAsync
                    await _transport.FlushAsync(System.Threading.CancellationToken.None);
                    
                    // If we have a client, try a minimal operation
                    if (_client != null)
                    {
                        // We could do a real "ping" operation here if the service supports it
                        // For now, we'll just check the transport state
                        return _transport.IsOpen;
                    }
                    
                    return true;
                }
                return false;
            }
            catch
            {
                _isConnected = false;
                return false;
            }
        }

        public void Disconnect()
        {
            if (_isConnected && _transport != null)
            {
                try
                {
                    _transport.Close();
                }
                catch
                {
                    // Ignore exceptions during close
                }
                finally
                {
                    _isConnected = false;
                }
            }
        }

        public bool IsConnected => _isConnected;

        public void Dispose()
        {
            Disconnect();
            _transport?.Dispose();
        }
        
        public async Task<bool> TrySay(string message)
        {
            try
            {
                await Client.say(message);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> TryPing()
        {
            try
            {
                return await Client.ping() == ERes.E_SUCCEED;
            }
            catch
            {
                return false;
            }
        }

        public async Task<(bool Success, ThLoginResult Result)> TryLoginController(ThUserInfo user, string hmiVersion)
        {
            try
            {
                var result = await Client.loginController(user, hmiVersion);
                _authToken = result.Token; // 保存Token
                return (true, result);
            }
            catch
            {
                _authToken = null; // 登录失败时清空Token
                return (false, null);
            }
        }

        public string GetAuthToken()
        {
            return _authToken; // 直接返回Token，不检查过期
        }

        public async Task<bool> TrySetManualServon(int robId, int nServOffOn)
        {
            try
            {
                await Client.setManualServon(_authToken, robId, nServOffOn);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> TrySetAllMsgClear()
        {
            try
            {
                await Client.setAllMsgClear(_authToken);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }

}